package edu.tsinghua.oxy.admin.listener;

import com.netflix.appinfo.InstanceInfo;
import edu.tsinghua.oxy.admin.service.MailService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent;
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.HashSet;
import java.util.Set;

/**
 * @author sean
 */
@Slf4j
@Component
public class JobSupervise {

    private final static DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private final static Set<String> services = new HashSet<>();

    @Resource
    MailService mailService;

    /**
     * 离线监听
     * @param event
     */
    @EventListener
    public void listen(EurekaInstanceCanceledEvent event) {
        String serviceId = event.getServerId();
        String appName = event.getAppName();
        // 已经下线的服务，我们不需要重复发送邮件，外层拦截
        if (services.contains(serviceId + appName)) {
            log.warn("[Out] This serviceId has canceled, serviceId : {}, appName : {}", serviceId, appName);
            return;
        }

        synchronized (this) {

            // 已经下线的服务，我们不需要重复发送邮件，内层拦截
            if (services.contains(serviceId + appName)) {
                log.warn("[In] This serviceId has canceled, serviceId : {}, appName : {}", serviceId, appName);
                return;
            }

            // 首次下线，添加发送邮件标志
            services.add(serviceId + appName);

            // 生成邮件内容邮件
            StringBuilder sb = new StringBuilder();
            sb.append("服务ID=");
            sb.append(serviceId);
            sb.append(System.getProperty("line.seperator", "\n"));
            sb.append("应用名=");
            sb.append(appName);
            sb.append(System.getProperty("line.seperator", "\n"));
            sb.append("时间=");
            sb.append(DTF.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(event.getTimestamp()), ZoneId.systemDefault())));

            mailService.sendSimpleMail("告警！！！后院着火了~~~", sb.toString());
        }

    }


    /**
     * 注册监听
     * @param event
     */
    @EventListener
    public void listen(EurekaInstanceRegisteredEvent event) {
        String serviceId = event.getInstanceInfo().getInstanceId();
        String appName = event.getInstanceInfo().getAppName();

        // 服务重启恢复后，删掉发送邮件标志
        if (event.getInstanceInfo().getStatus().equals(InstanceInfo.InstanceStatus.UP) &&
                services.contains(serviceId + appName)) {
            log.warn("register service again, services'size : {}, delete serviceKey : {}",
                    services.size(), serviceId + appName);
            services.remove(serviceId + appName);
        }
    }
}

